package com.gec.realm;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gec.entity.ActiveUser;
import com.gec.entity.Employee;
import com.gec.entity.MenuTree;
import com.gec.entity.SysPermission;
import com.gec.service.EmployeeService;
import com.gec.service.SysService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 自定义的Realm类继承AuthorizingRealm既可以用户授权也可以用户认证
 */
@Slf4j
public class MyRealm extends AuthorizingRealm {

    @Autowired
    private EmployeeService employeeService;

    @Autowired
    private HashedCredentialsMatcher matcher;

    @Autowired
    private SysService sysService;

    /**
     * 用户授权的方法,当用户认证后每次访问需要授权的地址时都需要执行这段代码来完成授权操作
     * 这里应该查询数据库并获取当前用户的所有角色和权限并且设置到shiro中
     *
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        log.info("授权用户...");

       ActiveUser activeUser = (ActiveUser) principals.getPrimaryPrincipal();

        //查询数据库认证用户拥有的角色和权限
        List<SysPermission> permissions = null;
        //查询权限列表
        permissions = sysService.findpermissionsByUserId(activeUser.getUsername());
        System.out.println(permissions);
        //将权限列表中的权限值放入集合中
        List<String> permissionList = new ArrayList<>();
        for (SysPermission permission : permissions) {
            System.out.println("授权: "+permission);
            permissionList.add(permission.getPercode());
        }

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addStringPermissions(permissionList);

        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        log.info("认证用户....");

        UsernamePasswordToken tk = (UsernamePasswordToken) token;

        String username = (String) tk.getPrincipal();

        //通过用户名从数据获取用户对象,用于比对请求传过来的用户名
        QueryWrapper<Employee> ew = new QueryWrapper<>();
        ew.eq("name", username);
        Employee employee = employeeService.getOne(ew);

        if (employee == null) {
            throw new UnknownAccountException();
        }

        //获取菜单根路径
        List<MenuTree> menuTrees = sysService.getMenuTree();

        //把用户的身份信息重新封装
        ActiveUser activeUser = new ActiveUser();
        activeUser.setId(employee.getId());
        activeUser.setUserid(employee.getName());
        activeUser.setUsercode(employee.getName());
        activeUser.setUsername(employee.getName());
        activeUser.setManagerId(employee.getManagerId());
        activeUser.setMenuTree(menuTrees);

        //获取密码加密的盐
        String salt = employee.getSalt();

        //设值密码加密器
        this.setCredentialsMatcher(matcher);

        return new SimpleAuthenticationInfo(activeUser, employee.getPassword(),ByteSource.Util.bytes(salt), getName());
    }
}
